/**
 * 实时语音识别客户端
 * 基于WebSocket连接到后端ASR服务
 */

import { AI_CHAT_API_BASE_URL } from './constants'

export class ASRClient {
  constructor() {
    this.ws = null
    this.isConnected = false
    this.audioContext = null
    this.mediaStream = null
    this.audioWorklet = null
    this.scriptProcessor = null
    this.analyser = null
    
    // 回调函数
    this.onTranscription = null
    this.onSpeechStart = null
    this.onSpeechStop = null
    this.onError = null
    this.onConnected = null
    
    this.isRecording = false
  }
  
  /**
   * 连接ASR服务
   * @param {Object} config - 配置参数
   * @param {string} config.language - 语言，默认'zh'
   * @param {number} config.sampleRate - 采样率，默认16000
   * @param {string} config.inputAudioFormat - 音频格式，默认'pcm'
   * @param {string} config.corpusText - 上下文文本（可选）
   * @param {boolean} config.enableTurnDetection - 是否启用VAD，默认true
   * @param {Function} callbacks.onTranscription - 识别结果回调 (text, isComplete)
   * @param {Function} callbacks.onSpeechStart - 语音开始回调
   * @param {Function} callbacks.onSpeechStop - 语音停止回调
   * @param {Function} callbacks.onError - 错误回调
   * @param {Function} callbacks.onConnected - 连接成功回调
   */
  async connect(config = {}, callbacks = {}) {
    const {
      language = 'zh',
      sampleRate = 16000,
      inputAudioFormat = 'pcm',
      corpusText = null,
      enableTurnDetection = true
    } = config
    
    this.onTranscription = callbacks.onTranscription
    this.onSpeechStart = callbacks.onSpeechStart
    this.onSpeechStop = callbacks.onSpeechStop
    this.onError = callbacks.onError
    this.onConnected = callbacks.onConnected
    
    return new Promise((resolve, reject) => {
      try {
        // 构建WebSocket URL
        const wsUrl = AI_CHAT_API_BASE_URL.replace('http://', 'ws://').replace('https://', 'wss://')
        this.ws = new WebSocket(`${wsUrl}/ws/asr`)
        
        this.ws.onopen = () => {
          console.log('[ASR] WebSocket连接已建立')
          
          // 发送配置
          this.ws.send(JSON.stringify({
            language,
            sample_rate: sampleRate,
            input_audio_format: inputAudioFormat,
            corpus_text: corpusText,
            enable_turn_detection: enableTurnDetection
          }))
        }
        
        this.ws.onmessage = (event) => {
          try {
            const data = JSON.parse(event.data)
            
            switch (data.type) {
              case 'connected':
                console.log('[ASR] ASR服务已连接')
                this.isConnected = true
                if (this.onConnected) this.onConnected()
                resolve()
                break
              
              case 'transcription':
                if (this.onTranscription) {
                  this.onTranscription(data.text, data.is_complete)
                }
                break
              
              case 'speech_start':
                console.log('[ASR] 检测到语音开始')
                if (this.onSpeechStart) this.onSpeechStart()
                break
              
              case 'speech_stop':
                console.log('[ASR] 检测到语音停止')
                if (this.onSpeechStop) this.onSpeechStop()
                break
              
              case 'error':
                console.error('[ASR] 错误:', data.message)
                if (this.onError) this.onError(data.message)
                break
            }
          } catch (e) {
            console.error('[ASR] 解析消息失败:', e)
          }
        }
        
        this.ws.onerror = (error) => {
          console.error('[ASR] WebSocket错误:', error)
          if (this.onError) this.onError('WebSocket连接错误')
          reject(error)
        }
        
        this.ws.onclose = () => {
          console.log('[ASR] WebSocket连接已关闭')
          this.isConnected = false
        }
      } catch (error) {
        console.error('[ASR] 连接失败:', error)
        reject(error)
      }
    })
  }
  
  /**
   * 获取分析器节点
   */
  getAnalyser() {
    return this.analyser
  }

  /**
   * 开始录音并发送音频数据
   */
  async startRecording() {
    try {
      // 请求麦克风权限
      this.mediaStream = await navigator.mediaDevices.getUserMedia({
        audio: {
          channelCount: 1,
          sampleRate: 16000,
          echoCancellation: true,
          noiseSuppression: true,
          autoGainControl: true
        }
      })
      
      // 创建音频上下文
      this.audioContext = new (window.AudioContext || window.webkitAudioContext)({
        sampleRate: 16000
      })
      
      const source = this.audioContext.createMediaStreamSource(this.mediaStream)
      
      // 创建分析器
      this.analyser = this.audioContext.createAnalyser()
      this.analyser.fftSize = 256

      // 使用ScriptProcessor处理音频（兼容性更好）
      const bufferSize = 4096
      this.scriptProcessor = this.audioContext.createScriptProcessor(bufferSize, 1, 1)
      
      this.scriptProcessor.onaudioprocess = (e) => {
        if (!this.isConnected || !this.ws || !this.isRecording) return
        
        const inputData = e.inputBuffer.getChannelData(0)
        
        // 转换为16位PCM
        const pcmData = this.floatTo16BitPCM(inputData)
        
        // 转换为Base64
        const base64Audio = this.arrayBufferToBase64(pcmData.buffer)
        
        // 发送音频数据
        this.ws.send(JSON.stringify({
          type: 'audio',
          audio: base64Audio
        }))
      }
      
      // 连接音频节点：source -> analyser -> scriptProcessor -> destination
      source.connect(this.analyser)
      this.analyser.connect(this.scriptProcessor)
      this.scriptProcessor.connect(this.audioContext.destination)
      
      console.log('[ASR] 开始录音')
    } catch (error) {
      console.error('[ASR] 开始录音失败:', error)
      if (this.onError) this.onError('无法访问麦克风')
      throw error
    }
  }
  
  /**
   * 停止录音
   */
  stopRecording() {
    this.isRecording = false
    
    if (this.scriptProcessor) {
      this.scriptProcessor.disconnect()
      this.scriptProcessor = null
    }
    
    if (this.mediaStream) {
      this.mediaStream.getTracks().forEach(track => track.stop())
      this.mediaStream = null
    }
    
    if (this.audioContext) {
      this.audioContext.close()
      this.audioContext = null
    }
    
    console.log('[ASR] 停止录音')
  }
  
  /**
   * 关闭ASR连接
   */
  close() {
    this.stopRecording()
    
    if (this.ws) {
      this.ws.send(JSON.stringify({ type: 'close' }))
      this.ws.close()
      this.ws = null
    }
    
    this.isConnected = false
    console.log('[ASR] 连接已关闭')
  }
  
  /**
   * 将Float32Array转换为16位PCM
   */
  floatTo16BitPCM(float32Array) {
    const int16Array = new Int16Array(float32Array.length)
    for (let i = 0; i < float32Array.length; i++) {
      const s = Math.max(-1, Math.min(1, float32Array[i]))
      int16Array[i] = s < 0 ? s * 0x8000 : s * 0x7FFF
    }
    return int16Array
  }
  
  /**
   * 将ArrayBuffer转换为Base64
   */
  arrayBufferToBase64(buffer) {
    let binary = ''
    const bytes = new Uint8Array(buffer)
    const len = bytes.byteLength
    for (let i = 0; i < len; i++) {
      binary += String.fromCharCode(bytes[i])
    }
    return window.btoa(binary)
  }
}
